package com.bikes.mileagetracker.utils

import android.Manifest
import android.content.pm.PackageManager
import android.os.Build
import android.support.v4.app.ActivityCompat
import com.bikes.mileagetracker.MileageTrackerApplication
import com.bikes.mileagetracker.entity.TrackingEntity
import com.bikes.mileagetracker.entity.UserEntity
import com.bikes.mileagetracker.service.PersistenceService
import org.apache.commons.lang3.StringUtils

interface Decide<R> {
    fun decide(): R
}

interface DecideOne<T, R> {
    fun decide(condition: T): R
}


interface BooleanDecide : Decide<Boolean>
interface BooleanDecideOne<T> : DecideOne<T, Boolean>

class AndDecide(val decides: Array<BooleanDecide>) : BooleanDecide {

    override fun decide(): Boolean {
        var res = true
        for (cur in decides) {
            res = res && cur.decide()
        }
        return res
    }
}


val androidPermissionGrantDecide: BooleanDecideOne<String> = object : BooleanDecideOne<String> {
    override fun decide(permission: String): Boolean {
        return ActivityCompat.checkSelfPermission(MileageTrackerApplication.getCurrentApplication(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
    }
}

val androidLocationPermissionOpenAnyDecide: BooleanDecide = object : BooleanDecide {
    override fun decide(): Boolean {
        return androidPermissionGrantDecide.decide(Manifest.permission.ACCESS_FINE_LOCATION) || androidPermissionGrantDecide.decide(Manifest.permission.ACCESS_COARSE_LOCATION)
    }
}

val androidLocationPermissionOpenAnyDecideRun: (() -> Unit) -> Unit = { function ->
    if (androidVersionAfter8V26Decide.decide()) {
        function()
    }
}


val androidLocationPermissionCloseAnyDecide: BooleanDecide = object : BooleanDecide {
    override fun decide(): Boolean {
        return !androidPermissionGrantDecide.decide(Manifest.permission.ACCESS_FINE_LOCATION) || !androidPermissionGrantDecide.decide(Manifest.permission.ACCESS_COARSE_LOCATION)
    }
}

val androidVersionAfter6V23Decide: BooleanDecide = object : BooleanDecide {
    override fun decide(): Boolean {
        return Build.VERSION.SDK_INT >= 23
    }
}

val androidVersionAfter6V23DecideRun: (() -> Unit) -> Unit = { function ->
    if (androidVersionAfter6V23Decide.decide()) {
        function()
    }
}

val androidVersionAfter8V26Decide: BooleanDecide = object : BooleanDecide {
    override fun decide(): Boolean {
        return Build.VERSION.SDK_INT >= 26
    }
}


val androidVersionAfter8V26DecideRun: (() -> Unit) -> Unit = { function ->
    if (androidVersionAfter8V26Decide.decide()) {
        function()
    }
}


val androidVersionAfter4d4wV20Decide: BooleanDecide = object : BooleanDecide {
    override fun decide(): Boolean {
        return Build.VERSION.SDK_INT >= 20
    }
}

val androidVersionAfter4d4wV20DecideRun: (() -> Unit) -> Unit = { function ->
    if (androidVersionAfter4d4wV20Decide.decide()) {
        function()
    }
}

val androidVersionAfter4d2V17Decide: BooleanDecide = object : BooleanDecide {
    override fun decide(): Boolean {
        return Build.VERSION.SDK_INT >= 17
    }
}

val androidVersionAfter4d2V17DecideRun: (() -> Unit) -> Unit = { function ->
    if (androidVersionAfter4d2V17Decide.decide()) {
        function()
    }
}

val whenPersistenceServiceReaderRun: (() -> Unit) -> Unit = { function ->
    if (PersistenceService.service != null) {
        TaskUtils.runInBackground {
            function()
        }
    }
}


val waitPersistenceServiceReaderRun: (() -> Unit) -> Unit = { function ->
    TaskUtils.runInBackground {
        while (PersistenceService.service == null) {
            Thread.sleep(100)
        }
        function()
    }
}

val existsCurrentUserDecide: BooleanDecide = object : BooleanDecide {
    override fun decide(): Boolean {
        val cuser = MileageTrackerApplication.getCurrentAccount()
        return cuser is UserEntity && StringUtils.isNotBlank(cuser.id)
    }
}

val isTrackingStarting: BooleanDecide = object : BooleanDecide {
    override fun decide(): Boolean {
        val ct = MileageTrackerApplication.getCurrentTracking()
        return ct is TrackingEntity && StringUtils.isNotBlank(ct.id)
    }
}

val isTrackingStoped: BooleanDecide = object : BooleanDecide {
    override fun decide(): Boolean {
        val ct = MileageTrackerApplication.getCurrentTracking()
        return ct !is TrackingEntity
    }
}

val isTrackingStopedRun: (() -> Unit) -> Unit = { function ->
    if (isTrackingStoped.decide()) {
        function()
    }
}

val whenExistsCurrentUserAndTrackingStartRun: (() -> Unit) -> Unit = { function ->
    if (AndDecide(arrayOf(existsCurrentUserDecide, isTrackingStarting)).decide()) {
        function()
    }
}

val isNotTrackingFromAddressDecide = object : BooleanDecide {
    override fun decide(): Boolean {
        return StringUtils.isBlank(MileageTrackerApplication.getCurrentTracking()?.startAddress
                ?: "")
    }
}



val whenNotTrackingFromAddressRun: (() -> Unit) -> Unit = { function ->
    if (isNotTrackingFromAddressDecide.decide()) {
        function()
    }
}

val whenOptionMapCenterFollowingRun: (() -> Unit) -> Unit = { function ->
    if (MileageTrackerApplication.MAP_CENTER_FOLLOWING) {
        function()
    }
}


